#pragma once

#include "ievent.h"
#include "epoll_reactor.h"
#include <unordered_map>
#include <unordered_set>
#include <shared_mutex>
#include <tuple>

class ServerHandle;
class ClientHandle;
class TcpServer;

class ITcpEvent {
public:
    virtual ~ITcpEvent() {}
    virtual void OnConnect(TcpServer& server, IHandle* h) = 0;
    virtual void OnRead(TcpServer& server, IHandle* h, const char* buf, int len) = 0;
    virtual void OnDisconnect(TcpServer& server, IHandle* h) = 0;
    virtual void OnServerLog(TcpServer& server, const std::string& log) = 0;
    virtual void OnClientLog(TcpServer& server, IHandle* h, const std::string& log) = 0;
};

class TcpServer : public IEvent {
public:
    //timeout: seconds
    TcpServer(ITcpEvent* event, time_t timeout = 60);
    ~TcpServer();
    std::tuple<bool, std::string> Init(const std::string& ip, int port, int backlog = 1024);
    //timeout: seconds
    void HandleEvents(time_t timeout);
    void Write(IHandle* h, const char* buf, int len);
    void Close(IHandle* h);

protected:
    void OnConnect(IHandle* h);
    void OnRead(IHandle* h, const char* buf, int len);
    void OnDisconnect(IHandle* h);
    void OnLog(IHandle* h, const std::string& log);

private:
    TcpServer(const TcpServer&) = delete;
    TcpServer& operator =(const TcpServer&) = delete;

protected:
    ITcpEvent* mTcpEvent;
    time_t mTimeout;
    time_t mLastTime;
    ServerHandle* mServer;
    std::unordered_map<ClientHandle*, time_t> mClients;
    std::shared_mutex mMutex;
    EpollReactor mEpoll;
};
